﻿using System;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Ink;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;
using System.Diagnostics;

namespace YourWorld.Common.Services
{
    public class SendMessageManager
    {
        private static SendMessageManager instance;
        private static readonly int ChunkSize = 128;
        private static readonly int ChunkOffset = 3 * 16;
        private static readonly int MessageSize = ChunkSize - ChunkOffset;

        private int lastSendMessageId = 0;
        private int uniqueClientId;

        public Action<byte[]> SendToServer;

        private SendMessageManager()
        {
        }

        public int UniqueClientId
        {
            get
            {
                return this.uniqueClientId;
            }
            set
            {
                this.uniqueClientId = value;
            }
        }

        public static SendMessageManager Instance
        {
            get
            {
                if ( instance == null )
                    instance = new SendMessageManager();

                return instance;
            }
        }

        /// <summary>
        /// Each sent data packet contains:
        ///  - unique message Id  - 16bit integer
        ///  - packets count      - 16bit integer
        ///  - packet number      - 16bit integer
        ///  - data
        /// </summary>
        /// <param name="message">The message that is to be send.</param>
        public void SendMessage( byte[] message )
        {
            Debug.Assert( this.SendToServer != null );

            ushort messageId = ( ushort )( this.UniqueClientId * 1000 + this.lastSendMessageId );
            byte[] messageIdBytes = BitConverter.GetBytes( messageId );

            this.lastSendMessageId++;

            if ( lastSendMessageId == 1000 )
                lastSendMessageId = 0;

            int messageLength = message.Length;
            int chunkLength = ChunkSize;

            int splitsCount = messageLength / MessageSize;
            if ( messageLength % MessageSize != 0 )
                splitsCount++;

            byte[] chunksCountBytes = BitConverter.GetBytes( ( ushort )splitsCount );
            byte[] chunkNoBytes;

            int i, j, c;

            for ( i = 0; i < splitsCount; i++ )
            {
                chunkNoBytes = BitConverter.GetBytes( ( ushort )i );

                if ( i == splitsCount - 1 )
                    chunkLength = messageLength % MessageSize + ChunkOffset;


                Debug.Assert( chunkLength <= 128 && messageIdBytes.Length == 16 &&
                    chunkNoBytes.Length == 16 && chunksCountBytes.Length == 16 );

                byte[] chunk = new byte[chunkLength];
                messageIdBytes.CopyTo( chunk, 0 );
                chunksCountBytes.CopyTo( chunk, 16 );
                chunkNoBytes.CopyTo( chunk, 32 );

                c = ChunkOffset;
                for ( j = 0; j < chunkLength - ChunkOffset; j++ )
                {
                    chunk[c] = message[i * MessageSize + j];
                    c++;
                }

                this.SendToServer( chunk );
            }
        }
    }
}
